package credis

import (
	"context"
	"fmt"
	"gitee.com/theegg/go-brick/app/service/app"
	"github.com/go-redis/redis/v8"
	"time"
)

// redis 中间结构
type CRedis struct {
	conn *redis.Client
	tag  string
}

// @title New
// @description 初始化一个redis
func New() *CRedis {
	op := new(CRedis)
	op.conn = app.RedisCache()
	return op
}

// @title Tag
// @description 设置一个tag,应用hash类型上，方便数据的flush
// @return *CRedis
func (c *CRedis) Tag(tag string) *CRedis {
	c.tag = tag
	return c
}

// @title Has
// @description 判断一个key是否存在
// @return bool, error
func (c CRedis) Has(key string) (bool, error) {
	var ctx = context.Background()

	res, errDel := c.conn.Exists(ctx, key).Result()
	if errDel != nil {
		return false, errDel
	}

	// 如果不存在
	if res == 0 {
		return false, nil
	}

	return true, nil
}

// @title Set
// @description 设置一个如果已存在则覆盖 注意没有 key 的过期时间, 另一种tag实现方式是冒号来处理分组可以实现单key过期
func (c CRedis) Set(key string, value string, expiration time.Duration) error {
	var ctx = context.Background()
	errSet := c.conn.Set(ctx, key, value, expiration).Err()
	if errSet != nil {
		return errSet
	}

	return nil
}

// @title TSet
// @description 设置一个如果已存在则覆盖 注意没有 key 的过期时间, 另一种tag实现方式是冒号来处理分组可以实现单key过期
func (c CRedis) TSet(key string, value []byte) (bool, error) {
	var ctx = context.Background()
	errTSet := c.conn.HSet(ctx, c.tag, key, value).Err()
	if errTSet != nil {
		return false, errTSet
	}

	return true, nil
}

// @title Add
// @description 设置一个值　key => value 如果已存在返回错误
func (c CRedis) Add(key string, value string, expiration time.Duration) {

}

// @title Get
// @description 如果已存在返回错误
// @return []byte, error
func (c CRedis) Get(key string, defaultValue ...interface{}) ([]byte, error) {
	var ctx = context.Background()
	data, errGet := c.conn.Get(ctx, key).Bytes()
	if errGet != nil {
		return nil, errGet
	}

	return data, nil
}

// @title TGet
// @description 通过Tag获取 一般 针对不在意时效的缓存 如果已存在返回错误
// @return []byte, error
func (c CRedis) TGet(key string) ([]byte, error) {
	var ctx = context.Background()
	data, errGet := c.conn.HGet(ctx, c.tag, key).Bytes()
	if errGet != nil {
		return nil, errGet
	}

	return data, nil
}

// @title Del
// @description 删除一个key, 如果已经存在
// @return bool, error
func (c CRedis) Del(key string) (bool, error) {
	var ctx = context.Background()

	res, errDel := c.conn.Del(ctx, key).Result()
	if errDel != nil {
		return false, errDel
	}

	// 删除0个表示, 不存在key　按成功处理
	if res == 0 {
		return true, nil
	}

	return true, nil
}

// @title Del
// @description 删除一个key, 如果已经存在
// @return bool, error
func (c CRedis) TDel(key string, field string) (bool, error) {
	var ctx = context.Background()

	res, errDel := c.conn.HDel(ctx, key, field).Result()
	if errDel != nil {
		return false, errDel
	}

	// 删除0个表示, 不存在key　按成功处理
	if res == 0 {
		return true, nil
	}

	return true, nil
}

/** ==================  Hash Map set/get/getAll  =============== */

// @title HSet
// @description 可以设置所有　可以设置单个field
func (c CRedis) HSet(key string, values interface{}) error {
	var ctx = context.Background()
	errTSet := c.conn.HSet(ctx, key, values).Err()
	if errTSet != nil {
		return errTSet
	}

	return nil
}

// @title HGet
// @description 获取hasMap指定的字段 是个[]byte
func (c CRedis) HGet(key string, field string) ([]byte, error) {
	var ctx = context.Background()
	data, err := c.conn.HGet(ctx, key, field).Bytes()
	if err != nil {
		return nil, err
	}

	return data, nil
}

// @title HGetAll
// @description 获取所有的hasMap
func (c CRedis) HGetAll(key string) (map[string]string, error) {
	var ctx = context.Background()
	data, err := c.conn.HGetAll(ctx, key).Result()
	if err != nil {
		return nil, err
	}

	return data, nil
}

// @title Forever
// @description 设置一个值　永不过期
// @return bool, error
func (c CRedis) Forever(key string, value string) (bool, error) {

	return true, nil
}

// @title FlushTag
// @description 删除 Tag 所有的数据
// @return bool
func (c CRedis) FlushTag() bool {
	var ctx = context.Background()
	fmt.Println(c.tag)
	errFlushTag := c.conn.Del(ctx, c.tag).Err()
	if errFlushTag != nil {
		fmt.Println(errFlushTag.Error())
		return false
	}

	return true
}

// @title FlushAll
// @description 删除所有的数据
// @return bool
func (c CRedis) FlushAll() bool {
	var ctx = context.Background()

	errFlush := c.conn.FlushAll(ctx).Err()
	if errFlush != nil {
		return false
	}

	return true
}

// @title GetTag
// @description 获取当前的tag
// @return bool
func (c CRedis) GetTag() string {
	return c.tag
}
